/*
** Xin YUAN, 2023, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////
#ifndef __CTL_GMATH_H__
#define __CTL_GMATH_H__
////////////////////////////////////////////////////////////////////////////////

#ifndef __CTL_MATH_H__
	#error gmath.h requires math.h to be included first.
#endif

////////////////////////////////////////////////////////////////////////////////
namespace CTL {
////////////////////////////////////////////////////////////////////////////////

#include "_base_/vec.h"
#include "_base_/mat2col.h"
#include "_base_/mat3col.h"
#include "_base_/mat4col.h"
#include "_base_/vecop.h"
#include "_base_/matop.h"
#include "_base_/transform.h"
#include "_base_/geometry.h"

//VecHelper

class VecHelper
{
public:
	template <typename T, class TTrait = CTL::DefaultCompareTrait<T>>
	static bool IsZero(const Vec2<T>& v) noexcept
	{
		return TTrait::IsEQ(v.coord.x, 0) && TTrait::IsEQ(v.coord.y, 0);
	}
	template <typename T, class TTrait = CTL::DefaultCompareTrait<T>>
	static bool IsZero(const Vec3<T>& v) noexcept
	{
		return TTrait::IsEQ(v.coord.x, 0) && TTrait::IsEQ(v.coord.y, 0) && TTrait::IsEQ(v.coord.z, 0);
	}
	template <typename T, class TTrait = CTL::DefaultCompareTrait<T>>
	static bool IsZero(const Vec4<T>& v) noexcept
	{
		return TTrait::IsEQ(v.coord.x, 0) && TTrait::IsEQ(v.coord.y, 0) && TTrait::IsEQ(v.coord.z, 0) && TTrait::IsEQ(v.coord.w, 0);
	}
};

//Vec2CompareTrait<T, TTrait>

template <class T, class TTrait = CTL::DefaultCompareTrait<typename T::ValueType>>
class Vec2CompareTrait
{
public:
	typedef T  ValueType;
	typedef TTrait  TraitType;

public:
	static bool IsEQ(const ValueType& t1, const ValueType& t2) noexcept
	{
		return TraitType::IsEQ(t1.coord.x, t2.coord.x) && TraitType::IsEQ(t1.coord.y, t2.coord.y);
	}
	static bool IsNE(const ValueType& t1, const ValueType& t2) noexcept
	{
		return TraitType::IsNE(t1.coord.x, t2.coord.x) || TraitType::IsNE(t1.coord.y, t2.coord.y);
	}
};

//Vec3CompareTrait<T, TTrait>

template <class T, class TTrait = CTL::DefaultCompareTrait<typename T::ValueType>>
class Vec3CompareTrait
{
public:
	typedef T  ValueType;
	typedef TTrait  TraitType;

public:
	static bool IsEQ(const ValueType& t1, const ValueType& t2) noexcept
	{
		return TraitType::IsEQ(t1.coord.x, t2.coord.x) && TraitType::IsEQ(t1.coord.y, t2.coord.y) && TraitType::IsEQ(t1.coord.z, t2.coord.z);
	}
	static bool IsNE(const ValueType& t1, const ValueType& t2) noexcept
	{
		return TraitType::IsNE(t1.coord.x, t2.coord.x) || TraitType::IsNE(t1.coord.y, t2.coord.y) || TraitType::IsNE(t1.coord.z, t2.coord.z);
	}
};

//Vec4CompareTrait<T, TTrait>

template <class T, class TTrait = CTL::DefaultCompareTrait<typename T::ValueType>>
class Vec4CompareTrait
{
public:
	typedef T  ValueType;
	typedef TTrait  TraitType;

public:
	static bool IsEQ(const ValueType& t1, const ValueType& t2) noexcept
	{
		return TraitType::IsEQ(t1.coord.x, t2.coord.x) && TraitType::IsEQ(t1.coord.y, t2.coord.y) && TraitType::IsEQ(t1.coord.z, t2.coord.z) && TraitType::IsEQ(t1.coord.w, t2.coord.w);
	}
	static bool IsNE(const ValueType& t1, const ValueType& t2) noexcept
	{
		return TraitType::IsNE(t1.coord.x, t2.coord.x) || TraitType::IsNE(t1.coord.y, t2.coord.y) || TraitType::IsNE(t1.coord.z, t2.coord.z) || TraitType::IsNE(t1.coord.w, t2.coord.w);
	}
};

////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
#endif
////////////////////////////////////////////////////////////////////////////////
